﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Microsoft.SharePoint;
using DocumentFormat.OpenXml.Packaging;
using System.Xml;
using System.IO;
using DocumentFormat.OpenXml.Spreadsheet;
using System.Data;
using ConsolidationTool.Common.Entities;
using System.Collections;
using System.Web.Script.Serialization;
using Microsoft.SharePoint.Administration;

namespace ConsolidationTool.Common
{
    public static class ControlExtensions
    {
        public static bool IsNullOrEmpty(this string str)
        {
            return string.IsNullOrEmpty(str);
        }
        public static bool IsNotNullOrEmpty(this string str)
        {
            return !string.IsNullOrEmpty(str);
        }
        public static object toObjDecimal(this string str)
        {
            decimal d = 0.00M;
            if (!decimal.TryParse(str, out d))
                return str;
            return d;
        }
        public static decimal toDecimal(this string str)
        {
            decimal d = 0.00M;
            decimal.TryParse(str, out d);

            return d;
        }

        public static koOutputEntity GetRow(this List<koOutputEntity> entitys, string accountcode)
        {
            if (entitys == null) return null;
            var row = entitys.FirstOrDefault(b => b.accountcode == accountcode);
            if (row != null)
                return row;
            return null;
        }

        public static decimal GetBudgetYTDValue(this List<koOutputEntity> entitys, ARTReportFromItem from, int month)
        { 
            var row = entitys.GetRow(from.identity);
            if (row == null) return 0.00M;
            var newFrom = (from.Clone() as ARTReportFromItem);
            newFrom.month = month;
            return row.GetBudgetYTDValue(newFrom);
        }

        public static decimal GetFieldValue(this List<koOutputEntity> entitys, string accountcode, string fieldname)
        {
            var value = 0.00M; 

            var row = entitys.GetRow(accountcode);
            if (row != null)
                value = BusinessService.decimalParse(row.TryGetValue(fieldname) + "");

            return value;
        }

        public static fsentity GetEntity(this List<fsentity> entitys, string accountcode)
        { 
            return entitys.FirstOrDefault(b => b.accountcode == accountcode);
        }

        public static object TryGetValue(this object obj, string field)
        {
            decimal value = 0.00M;
            if (obj == null) return value;
            var pro = obj.GetType().GetProperty(field);
            if (pro == null)
            {
                Utilities.Log(string.Format("[TryGetValue]: Faild {0}, object : {1}", field, new JavaScriptSerializer().Serialize(obj)));
                return null;
            }
            return pro.GetValue(obj, null);
        }

        public static void TrySetValue(this object obj, string field, object value)
        {
            var pro = obj.GetType().GetProperty(field);
            pro.SetValue(obj, value, null);
        }

        public static DataTable ToDataTable<T>(this IEnumerable<T> collection)
        {
            var props = typeof(T).GetProperties();
            var dt = new DataTable();
            dt.Columns.AddRange(props.Select(p => new DataColumn(p.Name, p.PropertyType)).ToArray());
            if (collection.Count() > 0)
            {
                for (int i = 0; i < collection.Count(); i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (var pi in props)
                    {
                        object obj = pi.GetValue(collection.ElementAt(i), null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    dt.LoadDataRow(array, true);
                }
            }
            return dt;
        }

        public static IEnumerable<System.Web.UI.Control> All(this System.Web.UI.ControlCollection controls)
        {
            foreach (System.Web.UI.Control control in controls)
            {
                foreach (var grandchild in control.Controls.All())
                    yield return grandchild;

                yield return control;
            }
        }

        public static IEnumerable<T> AllOfType<T>(this System.Web.UI.ControlCollection controls) where T : System.Web.UI.Control
        {
            foreach (System.Web.UI.Control control in controls)
            {
                foreach (var grandchild in control.Controls.AllOfType<T>())
                    yield return grandchild;

                if (control is T)
                    yield return control as T;
            }
        }

        public static IEnumerable<T> AllOfTypeNoRecursion<T>(this System.Web.UI.ControlCollection controls) where T : System.Web.UI.Control
        {
            foreach (System.Web.UI.Control control in controls)
            {
                if (control is T)
                    yield return control as T;

                foreach (var grandchild in control.Controls.AllOfTypeNoRecursion<T>())
                    yield return grandchild;
            }
        }
    }

    public class Utilities
    {
        public static List<string> NoFinancialValidatePage = new List<string>() { 
            "HR", "Quality&Safety", "Actual_NF1", "Actual_NF2", "Forecast_HR", "Budget_HR", "Budget_QS", "Budget_NF1", "Budget_NF2" 
        };

        public static List<string> ManualStartLists = new List<string>() { 
            "Common_Exchange_Rate_Actual" ,
            "Common_Exchange_Rate_Budget",
            "Common_Exchange_Rate_Forecast"
        };

        public static void Log(string source, TraceSeverity traceSeverity, EventSeverity eventSeverity, string logMessage)
        {
            try
            {
                SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory(source, traceSeverity, eventSeverity), traceSeverity, logMessage, null);
            }
            catch (Exception)
            {
                // maybe write to Event Log?
            }
        }
        public static void Log(string mess)
        {

            Log("requette", TraceSeverity.High, EventSeverity.Error, mess);
        }
        public static float parseToInt(string str)
        {
            float temp = 0;
            if (string.IsNullOrEmpty(str))
                return temp;

            str = str.Replace(",", "");
            if (float.TryParse(str, out temp))
                return temp;

            return temp;
        }

        public static string CreateItemIndentity(string ParentList, string CoCode, string Year, string Month)
        {
            return string.Format("{0}-{1}-{2}-{3}", ParentList, CoCode, Year, Month);
        }

        public static void UserRoleAssignment(Guid MysiteGuid, Guid MywebGuid, Guid listID, int listItemID, Entity SelectedEntity, SPRoleType roleType)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite MySite = new SPSite(MysiteGuid))
                {
                    using (SPWeb web = MySite.AllWebs[MywebGuid])
                    {
                        web.AllowUnsafeUpdates = true;
                        SPListItem listItem = web.Lists[listID].GetItemById(listItemID);

                        listItem.BreakRoleInheritance(true);

                        //foreach (SPRoleAssignment roleAssignment in listItem.RoleAssignments)
                        //{
                        //    roleAssignment.RoleDefinitionBindings.RemoveAll();
                        //    roleAssignment.Update();
                        //}

                        while (listItem.RoleAssignments.Count != 0)
                            listItem.RoleAssignments.Remove(0);

                        SPRoleDefinition role = listItem.Web.RoleDefinitions.GetByType(roleType);

                        SPRoleAssignment RegionAssignment = new SPRoleAssignment(SelectedEntity.Region);
                        SPRoleAssignment SubRegionAssignment = new SPRoleAssignment(SelectedEntity.SubRegionGroup);
                        RegionAssignment.RoleDefinitionBindings.Add(role);
                        SubRegionAssignment.RoleDefinitionBindings.Add(role);
                        listItem.RoleAssignments.Add(RegionAssignment);
                        listItem.RoleAssignments.Add(SubRegionAssignment);
                        //set mutil groups promission but if not no finance
                        SelectedEntity.Groups.ForEach(g =>
                        {
                            if (NoFinancialValidatePage.Contains(listItem.ParentList.Title) ||
                                (!NoFinancialValidatePage.Contains(listItem.ParentList.Title) &&
                                !g.Name.EndsWith("_NF")))
                            {
                                SPRoleAssignment EntityAssignment = new SPRoleAssignment(g);
                                EntityAssignment.RoleDefinitionBindings.Add(role);
                                listItem.RoleAssignments.Add(EntityAssignment);
                            }
                        });

                        listItem.Update();
                        web.AllowUnsafeUpdates = false;
                    }
                }
            });
        }

        public static void CloseForm()
        {
            HttpContext.Current.Response.Write("<script type='text/javascript'>window.frameElement.commitPopup();</script>");
            //HttpContext.Current.Response.Write("<script type='text/javascript'>window.frameElement.commonModalDialogClose(1,'success');</script>");
            HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.End();
        }
        public static string GetItemValue(SPListItem item, string fieldName)
        {
            string rst = string.Empty;
            if (item.Fields.TryGetFieldByStaticName(fieldName) != null)
                rst = item[fieldName] + "";
            return rst == "" ? "0" : rst;
        }

        public static System.Data.DataTable GetSheets(Stream stream)
        {
            List<String> sheets1 = new List<String>();

            System.Data.DataTable dt = new System.Data.DataTable();
            using (SpreadsheetDocument xlPackage = SpreadsheetDocument.Open(stream, false))
            {
                WorkbookPart workbook = xlPackage.WorkbookPart;
                Stream workbookstr = workbook.GetStream();
                XmlDocument doc = new XmlDocument();
                doc.Load(workbookstr);
                XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
                nsManager.AddNamespace("default", doc.DocumentElement.NamespaceURI);
                XmlNodeList nodelist = doc.SelectNodes("//default:sheets/default:sheet", nsManager);
                foreach (XmlNode node in nodelist)
                {
                    String sheetName = String.Empty;
                    sheetName = node.Attributes["name"].Value;
                    sheets1.Add(sheetName);
                }
                IEnumerable<Sheet> sheets = xlPackage.WorkbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name.ToString().ToLower() == sheets1.First().ToLower());
                if (sheets.Count() == 0)
                    return null;
                dt.TableName = sheets1.First().ToLower();

                WorksheetPart worksheetPart = (WorksheetPart)xlPackage.WorkbookPart.GetPartById(sheets.First().Id);
                Worksheet worksheet = worksheetPart.Worksheet;
                //Ignore row header 
                IEnumerable<Row> rows = worksheet.Descendants<Row>();

                bool haveBeenHeader = false;

                foreach (Row row in rows)
                {
                    var dtrow = dt.NewRow();
                    int index = 0;
                    bool rowHaveValue = false;

                    foreach (Cell cell in row)
                    {
                        var value = GetValue(cell, xlPackage.WorkbookPart.SharedStringTablePart);
                        if (string.IsNullOrEmpty(value))
                        {
                            index++;
                            continue;
                        }
                        rowHaveValue = true;

                        if (!haveBeenHeader)
                            dt.Columns.Add(new DataColumn(value));
                        else
                        {
                            dtrow[index] = value;
                            index++;
                        }
                        // Console.WriteLine(value);

                    }
                    if (haveBeenHeader && rowHaveValue)
                        dt.Rows.Add(dtrow);
                    haveBeenHeader = true;
                }
            }
            return dt;
        }
        public static String GetValue(Cell cell, SharedStringTablePart stringTablePart)
        {

            if (cell.ChildElements.Count == 0)

                return null;

            //get cell value

            String value = cell.CellValue.InnerText;

            //Look up real value from shared string table

            if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))

                value = stringTablePart.SharedStringTable

                .ChildElements[Int32.Parse(value)]

                .InnerText;

            return value;

        }


        public static string Division(string p, string p_2, bool division100)
        {
            return Division(p, p_2, division100, 3);
        }
        public static string Division(string p, string p_2)
        {
            return Division(p, p_2, true, 3);
        }
        public static string Division(string p, string p_2, bool division100, int num)
        {
            decimal a, b;
            decimal.TryParse(p, out a);
            decimal.TryParse(p_2, out b);

            if (b == 0)
                return "0";
            if (division100)
                return ((a / b) * 100).ToString("N" + num);
            else
                return ((a / b)).ToString("N" + num);
        }
        public static decimal Division(decimal p, decimal p_2)
        {
            if (p_2 == 0)
                return 0;
            return p / p_2;
        }
        public static void Alert(string p)
        {

        }

        public static void Alert(System.Web.UI.Page Page, string p)
        {
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "_fs_Notice", string.Format("alert('{0}');", p), true);
        }

        public static int StrEncryptionCompress(object obj)
        {
            string str = new JavaScriptSerializer().Serialize(obj);
            int i = 0;
            str.ToArray().ToList().ForEach(p => i += (int)p);
            return i;
        }

    }
}
